package com.yc.cloud.admin.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yc.cloud.admin.dto.mediakit.MediaKitOnRecordMp4Hook;
import com.yc.cloud.admin.service.VideoRecordProcessService;
import com.yc.cloud.admin.utils.FFmpegUtils;
import com.yc.cloud.common.oss.entity.OssFile;
import com.yc.cloud.common.oss.service.OssFileService;
import com.yc.cloud.admin.service.HwDeviceVideoRecordService;
import com.yc.cloud.entity.HwCamera;
import com.yc.cloud.entity.HwDeviceVideoRecord;
import com.yc.cloud.mapper.HwCameraMapper;
import com.yc.cloud.mapper.HwDeviceCameraMapper;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 * 录像处理服务实现类
 * </p>
 *
 * @author kinggu
 * @since 2025-01-03
 */
@Service
@Slf4j
public class VideoRecordProcessServiceImpl implements VideoRecordProcessService {

    @Resource
    private HwCameraMapper hwCameraMapper;

    @Resource
    private HwDeviceCameraMapper hwDeviceCameraMapper;

    @Resource
    private FFmpegUtils ffmpegUtils;

    @Resource
    private HwDeviceVideoRecordService hwDeviceVideoRecordService;

    @Value("${custom.mediakit.record.orginPath}")
    private String orginPath;
    @Value("${custom.mediakit.record.customizedPath}")
    private String customizedPath;
    
    // 缩略图配置
    @Value("${custom.thumbnail.width:1280}")
    private Integer thumbnailWidth;
    @Value("${custom.thumbnail.height:720}")
    private Integer thumbnailHeight;
    @Value("${custom.thumbnail.quality:2}")
    private Integer thumbnailQuality;

    @Resource
    private OssFileService ossFileService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean processVideoRecord(MediaKitOnRecordMp4Hook payload) {
        try {
            log.info("Processing video record: stream={}, filePath={}", payload.getStream(), payload.getFilePath());

            // 1. 解析stream获取摄像头信息
            HwCamera camera = parseCameraFromStream(payload.getStream());
            if (camera == null) {
                log.warn("Failed to find camera from stream: {}", payload.getStream());
                // 如果找不到摄像头，仍然继续处理，但不设置摄像头ID
            }

            // 移动文件并创建OSS记录,这里的filepath 做了处理，需要根据配置文件中的orginPath 和 customizedPath 进行处理
            String finalFilePath = payload.getFilePath().replace(orginPath, customizedPath);
            log.info("文件最终路径地址：{}", finalFilePath);
            payload.setFilePath(finalFilePath);

            // 构建自定义目标路径 - 您可以根据需要修改这个路径构建逻辑
            String targetPath = buildCustomTargetPath(payload.getStream(), payload.getFilePath());
            String fileId = hwDeviceVideoRecordService.moveVideoFileAndCreateOssRecord(payload.getFilePath(),
                    targetPath);
            if (StrUtil.isEmpty(fileId)) {
                log.error("Failed to move video file and create OSS record: {}", payload.getFilePath());
                return false;
            }

            // 3. 保存录像记录 - 直接使用 MyBatis Plus 的 save 方法
            HwDeviceVideoRecord record = new HwDeviceVideoRecord();

            // 获取截图,通过ffmpegUtils来获取
            String thumbnail = generateThumbnail(targetPath);
            log.info("截图: {}", thumbnail);
            if (StrUtil.isNotEmpty(thumbnail)) {
                OssFile thumbnailOssFile = ossFileService.saveOssFile(thumbnail);
                if (thumbnailOssFile != null) {
                    record.setThumbnailFileId(thumbnailOssFile.getFileId());
                }
            }
            // record.setDeviceId(deviceId);
            record.setStream(payload.getStream());
            record.setStartTime(
                    LocalDateTime.ofInstant(Instant.ofEpochSecond(payload.getStartTime()), ZoneId.systemDefault()));
            record.setEndTime(
                    LocalDateTime.ofInstant(Instant.ofEpochSecond(payload.getEndTime()), ZoneId.systemDefault()));
            record.setDuration(payload.getDuration().intValue());
            record.setFileSize(payload.getFileSize());
            record.setOriginalFilePath(payload.getFilePath());
            record.setFileId(fileId);
            // 设置摄像头关联
            if (camera != null) {
                record.setCameraId(camera.getId());
                
                // 通过摄像头ID查询关联的设备ID（使用Mapper层方法）
                Long deviceId = hwDeviceCameraMapper.selectDeviceIdByCameraId(camera.getId());
                if (deviceId != null) {
                    record.setDeviceId(deviceId);
                    log.info("通过摄像头ID {} 查询到设备ID: {}", camera.getId(), deviceId);
                } else {
                    log.warn("摄像头 {} 未绑定设备", camera.getId());
                }
            }

            boolean saved = hwDeviceVideoRecordService.save(record);

            // log.info("Successfully processed video record: deviceId={}, recordId={}, fileId={}, saved={}",
            //         deviceId, record.getId(), fileId, saved);
            return true;

        } catch (Exception e) {
            log.error("Failed to process video record: stream={}, filePath={}",
                    payload.getStream(), payload.getFilePath(), e);
            return false;
        }
    }

    /**
     * 从stream中解析摄像头信息
     * stream格式：sipUsername_videoChannel
     * 需要根据sipUsername和videoChannel查找对应的摄像头
     * 
     * @param stream 流ID
     * @param selectOne TODO
     * @return 摄像头对象
     */
    private HwCamera parseCameraFromStream(String stream) {
 
        try {
            if (StrUtil.isEmpty(stream)) {
                return null;
            }

            // 解析stream，格式：sipUsername_videoChannel
            String[] parts = stream.split("_");
            if (parts.length != 2) {
                log.warn("Invalid stream format, expected sipUsername_videoChannel: {}", stream);
                return null;
            }

            String sipUsername = parts[0];
            String videoChannel = parts[1];

            // 根据sipUsername和videoChannel查找摄像头
            HwCamera camera =  hwCameraMapper.selectOne(
                new QueryWrapper<HwCamera>()
                        .eq(HwCamera.SipUsername, sipUsername)
                        .eq(HwCamera.VideoChannel, videoChannel));

            if (camera != null) {
                log.debug("Found camera: id={}, name={}, sipUsername={}, videoChannel={}",
                        camera.getId(), camera.getName(), sipUsername, videoChannel);
                return camera;
            } else {
                log.warn("Camera not found for stream: {}, sipUsername={}, videoChannel={}",
                        stream, sipUsername, videoChannel);
                return null;
            }

        } catch (Exception e) {
            log.error("Failed to parse camera from stream: {}", stream, e);
            return null;
        }
    }

    /**
     * 生成视频缩略图
     * @param videoPath 视频文件路径
     * @return 缩略图文件路径
     */
    public String generateThumbnail(String videoPath) {
        try {
            // 构建缩略图输出路径 - 与视频文件在同一目录，只是扩展名不同
            String thumbnailPath = buildThumbnailPath(videoPath);
            
            // 使用配置的分辨率和质量生成缩略图
            String thumbnail = ffmpegUtils.captureFrame(videoPath, thumbnailPath, null, thumbnailWidth, thumbnailHeight, thumbnailQuality);
            
            log.info("生成缩略图: 视频={}, 缩略图={}, 分辨率={}x{}", 
                    videoPath, thumbnail, thumbnailWidth, thumbnailHeight);
            return thumbnail;
            
        } catch (Exception e) {
            log.error("生成缩略图失败: videoPath={}, 分辨率={}x{}", 
                     videoPath, thumbnailWidth, thumbnailHeight, e);
            // 如果指定分辨率失败，尝试使用默认方式
            return ffmpegUtils.captureFrame(videoPath);
        }
    }
    
    /**
     * 构建缩略图文件路径
     * @param videoPath 视频文件路径
     * @return 缩略图文件路径
     */
    private String buildThumbnailPath(String videoPath) {
        // 获取视频文件的目录和文件名
        String directory = cn.hutool.core.io.FileUtil.getParent(videoPath, 1);
        String fileName = cn.hutool.core.io.FileUtil.getPrefix(videoPath); // 获取不带扩展名的文件名
        
        // 构建缩略图路径：同一目录下，文件名相同但扩展名为.jpg
        return java.nio.file.Paths.get(directory, fileName + ".jpg").toString();
    }

    /**
     * 构建自定义目标路径
     * 您可以根据业务需求修改这个方法的实现逻辑
     * 
     * @param stream           流ID
     * @param originalFilePath 原始文件路径
     * @return 自定义目标路径
     */
    private String buildCustomTargetPath(String stream, String originalFilePath) {
        // 示例：您可以根据需要修改路径构建逻辑
        // 这里提供几种常见的路径构建方式，您可以选择或修改：

        // 方式1：使用默认路径（与原来的逻辑相同）
        // return null; // 返回null将使用默认的buildTargetPath逻辑

        // 方式2：基于时间和流ID构建路径
        String fileName = cn.hutool.core.io.FileUtil.getName(originalFilePath);
        String dateStr = cn.hutool.core.date.DateUtil.format(java.time.LocalDateTime.now(), "yyyy-MM-dd");
        return java.nio.file.Paths.get(customizedPath, stream, dateStr, fileName).toString();

        // 方式3：您可以添加更多自定义逻辑
        // 例如：根据设备类型、区域等信息构建不同的路径结构
        // String deviceType = getDeviceTypeByStream(stream);
        // return Paths.get(customizedPath, "videos", deviceType, stream, dateStr,
        // fileName).toString();
    }
}
